home *** CD-ROM | disk | FTP | other *** search
/ Java Primer Plus / Java Primer Plus (Waite Group Proess)(1996).iso / java_Win / demo / Animator / Animator.class (.txt) next >
Encoding:
Java Class File  |  1995-10-12  |  14.5 KB  |  601 lines

  1. import java.applet.Applet;
  2. import java.applet.AudioClip;
  3. import java.awt.Color;
  4. import java.awt.Component;
  5. import java.awt.Dimension;
  6. import java.awt.Event;
  7. import java.awt.Graphics;
  8. import java.awt.Image;
  9. import java.awt.Point;
  10. import java.net.MalformedURLException;
  11. import java.net.URL;
  12. import java.util.Enumeration;
  13. import java.util.Hashtable;
  14. import java.util.Vector;
  15.  
  16. public class Animator extends Applet implements Runnable {
  17.    Vector images;
  18.    Hashtable durations;
  19.    Hashtable sounds;
  20.    Hashtable positions;
  21.    URL backgroundImageURL;
  22.    Image backgroundImage;
  23.    URL startUpImageURL;
  24.    Image startUpImage;
  25.    URL soundtrackURL;
  26.    AudioClip soundtrack;
  27.    int maxWidth;
  28.    int maxHeight;
  29.    boolean imageLoadError = false;
  30.    URL imageSource;
  31.    URL soundSource;
  32.    Thread engine;
  33.    int frameNum;
  34.    Integer frameNumKey;
  35.    int xPos;
  36.    int yPos;
  37.    public static final int defaultPause = 3900;
  38.    int globalPause = 3900;
  39.    boolean userPause = false;
  40.    boolean repeat;
  41.    boolean loadFirst;
  42.    Image offScrImage;
  43.    Graphics offScrGC;
  44.    boolean loaded = false;
  45.    boolean error = false;
  46.    static final String imageLabel = "image";
  47.    static final String soundLabel = "sound";
  48.    boolean debug = false;
  49.  
  50.    public String getAppletInfo() {
  51.       return "Animator by Herb Jellinek";
  52.    }
  53.  
  54.    public String[][] getParameterInfo() {
  55.       String[][] info = new String[][]{{"imagesource", "url", "a directory"}, {"startup", "url", "displayed at startup"}, {"background", "url", "displayed as background"}, {"startimage", "int", "start index"}, {"endimage", "int", "end index"}, {"pause", "int", "milliseconds"}, {"pauses", "ints", "milliseconds"}, {"repeat", "boolean", "repeat or not"}, {"positions", "coordinates", "path"}, {"soundsource", "url", "audio directory"}, {"soundtrack", "url", "background music"}, {"sounds", "urls", "audio samples"}};
  56.       return info;
  57.    }
  58.  
  59.    void dbg(String s) {
  60.       if (this.debug) {
  61.          System.out.println(s);
  62.       }
  63.  
  64.    }
  65.  
  66.    final int setFrameNum(int newFrameNum) {
  67.       this.frameNumKey = new Integer(this.frameNum = newFrameNum);
  68.       return this.frameNum;
  69.    }
  70.  
  71.    public synchronized boolean imageUpdate(Image img, int infoFlags, int x, int y, int width, int height) {
  72.       if ((infoFlags & 64) != 0) {
  73.          this.imageLoadError = true;
  74.       }
  75.  
  76.       this.notifyAll();
  77.       return true;
  78.    }
  79.  
  80.    void updateMaxDims(Dimension dim) {
  81.       this.maxWidth = Math.max(dim.width, this.maxWidth);
  82.       this.maxHeight = Math.max(dim.height, this.maxHeight);
  83.    }
  84.  
  85.    Vector parseImages(String attr) {
  86.       Vector result = new Vector(10);
  87.  
  88.       int next;
  89.       for(int i = 0; i < attr.length(); i = next + 1) {
  90.          next = attr.indexOf(124, i);
  91.          if (next == -1) {
  92.             next = attr.length();
  93.          }
  94.  
  95.          String file = attr.substring(i, next);
  96.          result.addElement(file);
  97.       }
  98.  
  99.       return result;
  100.    }
  101.  
  102.    URL fetchImages(Vector images) {
  103.       for(int i = 0; i < images.size(); ++i) {
  104.          Object o = images.elementAt(i);
  105.          if (o instanceof URL) {
  106.             URL url = (URL)o;
  107.             this.tellLoadingMsg(url, "image");
  108.             Image im = ((Applet)this).getImage(url);
  109.  
  110.             try {
  111.                this.updateMaxDims(this.getImageDimensions(im));
  112.             } catch (Exception var6) {
  113.                return url;
  114.             }
  115.  
  116.             images.setElementAt(im, i);
  117.          }
  118.       }
  119.  
  120.       return null;
  121.    }
  122.  
  123.    Hashtable parseSounds(String attr, Vector images) throws MalformedURLException {
  124.       Hashtable result = new Hashtable();
  125.       int imageNum = 0;
  126.       int numImages = images.size();
  127.  
  128.       for(int i = 0; i < attr.length() && imageNum < numImages; ++imageNum) {
  129.          int next = attr.indexOf(124, i);
  130.          if (next == -1) {
  131.             next = attr.length();
  132.          }
  133.  
  134.          String sound = attr.substring(i, next);
  135.          if (sound.length() != 0) {
  136.             result.put(new Integer(imageNum), new URL(this.soundSource, sound));
  137.          }
  138.  
  139.          i = next + 1;
  140.       }
  141.  
  142.       return result;
  143.    }
  144.  
  145.    URL fetchSounds(Hashtable sounds) {
  146.       Enumeration e = sounds.keys();
  147.  
  148.       while(e.hasMoreElements()) {
  149.          Integer num = (Integer)e.nextElement();
  150.          Object o = sounds.get(num);
  151.          if (o instanceof URL) {
  152.             URL file = (URL)o;
  153.             this.tellLoadingMsg(file, "sound");
  154.  
  155.             try {
  156.                sounds.put(num, ((Applet)this).getAudioClip(file));
  157.             } catch (Exception var6) {
  158.                return file;
  159.             }
  160.          }
  161.       }
  162.  
  163.       return null;
  164.    }
  165.  
  166.    Hashtable parseDurations(String attr, Vector images) {
  167.       Hashtable result = new Hashtable();
  168.       int imageNum = 0;
  169.       int numImages = images.size();
  170.  
  171.       for(int i = 0; i < attr.length() && imageNum < numImages; ++imageNum) {
  172.          int next = attr.indexOf(124, i);
  173.          if (next == -1) {
  174.             next = attr.length();
  175.          }
  176.  
  177.          if (i != next - 1) {
  178.             int duration = Integer.parseInt(attr.substring(i, next));
  179.             result.put(new Integer(imageNum), new Integer(duration));
  180.          } else {
  181.             result.put(new Integer(imageNum), new Integer(this.globalPause));
  182.          }
  183.  
  184.          i = next + 1;
  185.       }
  186.  
  187.       return result;
  188.    }
  189.  
  190.    Point parsePoint(String s) throws ParseException {
  191.       int atPos = s.indexOf(64);
  192.       if (atPos == -1) {
  193.          throw new ParseException("Illegal position: " + s);
  194.       } else {
  195.          return new Point(Integer.parseInt(s.substring(0, atPos)), Integer.parseInt(s.substring(atPos + 1)));
  196.       }
  197.    }
  198.  
  199.    Hashtable parsePositions(String param, Vector images) throws ParseException {
  200.       Hashtable result = new Hashtable();
  201.       int imageNum = 0;
  202.       int numImages = images.size();
  203.  
  204.       for(int i = 0; i < param.length() && imageNum < numImages; ++imageNum) {
  205.          int next = param.indexOf(124, i);
  206.          if (next == -1) {
  207.             next = param.length();
  208.          }
  209.  
  210.          if (i != next) {
  211.             result.put(new Integer(imageNum), this.parsePoint(param.substring(i, next)));
  212.          }
  213.  
  214.          i = next + 1;
  215.       }
  216.  
  217.       return result;
  218.    }
  219.  
  220.    synchronized Dimension getImageDimensions(Image im) throws ImageNotFoundException {
  221.       while(true) {
  222.          int width;
  223.          if ((width = im.getWidth(this)) < 0) {
  224.             try {
  225.                this.wait();
  226.             } catch (InterruptedException var5) {
  227.             }
  228.  
  229.             if (!this.imageLoadError) {
  230.                continue;
  231.             }
  232.  
  233.             throw new ImageNotFoundException(im.getSource());
  234.          }
  235.  
  236.          int height;
  237.          while((height = im.getHeight(this)) < 0) {
  238.             try {
  239.                this.wait();
  240.             } catch (InterruptedException var4) {
  241.             }
  242.  
  243.             if (this.imageLoadError) {
  244.                throw new ImageNotFoundException(im.getSource());
  245.             }
  246.          }
  247.  
  248.          return new Dimension(width, height);
  249.       }
  250.    }
  251.  
  252.    Vector prepareImageRange(int startImage, int endImage) throws MalformedURLException {
  253.       Vector result = new Vector(Math.abs(endImage - startImage) + 1);
  254.       if (startImage > endImage) {
  255.          for(int i = startImage; i >= endImage; --i) {
  256.             result.addElement(new URL(this.imageSource, "T" + i + ".gif"));
  257.          }
  258.       } else {
  259.          for(int i = startImage; i <= endImage; ++i) {
  260.             result.addElement(new URL(this.imageSource, "T" + i + ".gif"));
  261.          }
  262.       }
  263.  
  264.       return result;
  265.    }
  266.  
  267.    public void init() {
  268.       try {
  269.          String param = ((Applet)this).getParameter("IMAGESOURCE");
  270.          this.imageSource = param == null ? ((Applet)this).getDocumentBase() : new URL(((Applet)this).getDocumentBase(), param + "/");
  271.          this.dbg("IMAGESOURCE = " + param);
  272.          param = ((Applet)this).getParameter("PAUSE");
  273.          this.globalPause = param != null ? Integer.parseInt(param) : 3900;
  274.          this.dbg("PAUSE = " + param);
  275.          param = ((Applet)this).getParameter("REPEAT");
  276.          this.repeat = param == null ? true : param.equalsIgnoreCase("yes") || param.equalsIgnoreCase("true");
  277.          int startImage = 1;
  278.          int endImage = 1;
  279.          param = ((Applet)this).getParameter("ENDIMAGE");
  280.          this.dbg("ENDIMAGE = " + param);
  281.          if (param != null) {
  282.             endImage = Integer.parseInt(param);
  283.             param = ((Applet)this).getParameter("STARTIMAGE");
  284.             this.dbg("STARTIMAGE = " + param);
  285.             if (param != null) {
  286.                startImage = Integer.parseInt(param);
  287.             }
  288.  
  289.             this.images = this.prepareImageRange(startImage, endImage);
  290.          } else {
  291.             param = ((Applet)this).getParameter("STARTIMAGE");
  292.             this.dbg("STARTIMAGE = " + param);
  293.             if (param != null) {
  294.                startImage = Integer.parseInt(param);
  295.                this.images = this.prepareImageRange(startImage, endImage);
  296.             } else {
  297.                param = ((Applet)this).getParameter("IMAGES");
  298.                if (param == null) {
  299.                   ((Applet)this).showStatus("No legal IMAGES, STARTIMAGE, or ENDIMAGE specified.");
  300.                   return;
  301.                }
  302.  
  303.                this.images = this.parseImages(param);
  304.             }
  305.          }
  306.  
  307.          param = ((Applet)this).getParameter("BACKGROUND");
  308.          this.dbg("BACKGROUND = " + param);
  309.          if (param != null) {
  310.             this.backgroundImageURL = new URL(this.imageSource, param);
  311.          }
  312.  
  313.          param = ((Applet)this).getParameter("STARTUP");
  314.          this.dbg("STARTUP = " + param);
  315.          if (param != null) {
  316.             this.startUpImageURL = new URL(this.imageSource, param);
  317.          }
  318.  
  319.          param = ((Applet)this).getParameter("SOUNDSOURCE");
  320.          this.soundSource = param == null ? this.imageSource : new URL(((Applet)this).getDocumentBase(), param + "/");
  321.          this.dbg("SOUNDSOURCE = " + param);
  322.          param = ((Applet)this).getParameter("SOUNDS");
  323.          this.dbg("SOUNDS = " + param);
  324.          if (param != null) {
  325.             this.sounds = this.parseSounds(param, this.images);
  326.          }
  327.  
  328.          param = ((Applet)this).getParameter("PAUSES");
  329.          this.dbg("PAUSES = " + param);
  330.          if (param != null) {
  331.             this.durations = this.parseDurations(param, this.images);
  332.          }
  333.  
  334.          param = ((Applet)this).getParameter("POSITIONS");
  335.          this.dbg("POSITIONS = " + param);
  336.          if (param != null) {
  337.             this.positions = this.parsePositions(param, this.images);
  338.          }
  339.  
  340.          param = ((Applet)this).getParameter("SOUNDTRACK");
  341.          this.dbg("SOUNDTRACK = " + param);
  342.          if (param != null) {
  343.             this.soundtrackURL = new URL(this.soundSource, param);
  344.          }
  345.       } catch (MalformedURLException e) {
  346.          this.showParseError(e);
  347.       } catch (ParseException e) {
  348.          this.showParseError(e);
  349.       }
  350.  
  351.       this.setFrameNum(0);
  352.    }
  353.  
  354.    void tellLoadingMsg(String file, String fileType) {
  355.       ((Applet)this).showStatus("Animator: loading " + fileType + " " + abridge(file, 20));
  356.    }
  357.  
  358.    void tellLoadingMsg(URL url, String fileType) {
  359.       this.tellLoadingMsg(url.toExternalForm(), fileType);
  360.    }
  361.  
  362.    void clearLoadingMessage() {
  363.       ((Applet)this).showStatus("");
  364.    }
  365.  
  366.    static String abridge(String s, int len) {
  367.       String ellipsis = "...";
  368.       if (len >= s.length()) {
  369.          return s;
  370.       } else {
  371.          int trim = len - ellipsis.length();
  372.          return s.substring(0, trim / 2) + ellipsis + s.substring(s.length() - trim / 2);
  373.       }
  374.    }
  375.  
  376.    void loadError(URL badURL, String fileType) {
  377.       String errorMsg = "Animator: Couldn't load " + fileType + " " + badURL.toExternalForm();
  378.       ((Applet)this).showStatus(errorMsg);
  379.       System.err.println(errorMsg);
  380.       this.error = true;
  381.       ((Component)this).repaint();
  382.    }
  383.  
  384.    void showParseError(Exception e) {
  385.       String errorMsg = "Animator: Parse error: " + e;
  386.       ((Applet)this).showStatus(errorMsg);
  387.       System.err.println(errorMsg);
  388.       this.error = true;
  389.       ((Component)this).repaint();
  390.    }
  391.  
  392.    void startPlaying() {
  393.       if (this.soundtrack != null) {
  394.          this.soundtrack.loop();
  395.       }
  396.  
  397.    }
  398.  
  399.    void stopPlaying() {
  400.       if (this.soundtrack != null) {
  401.          this.soundtrack.stop();
  402.       }
  403.  
  404.    }
  405.  
  406.    public void run() {
  407.       Thread me = Thread.currentThread();
  408.       me.setPriority(1);
  409.       if (!this.loaded) {
  410.          try {
  411.             if (this.startUpImageURL != null) {
  412.                this.tellLoadingMsg(this.startUpImageURL, "image");
  413.                this.startUpImage = ((Applet)this).getImage(this.startUpImageURL);
  414.  
  415.                try {
  416.                   this.updateMaxDims(this.getImageDimensions(this.startUpImage));
  417.                } catch (Exception var12) {
  418.                   this.loadError(this.startUpImageURL, "start-up image");
  419.                }
  420.  
  421.                ((Component)this).resize(this.maxWidth, this.maxHeight);
  422.                ((Component)this).repaint();
  423.             }
  424.  
  425.             if (this.backgroundImageURL != null) {
  426.                this.tellLoadingMsg(this.backgroundImageURL, "image");
  427.                this.backgroundImage = ((Applet)this).getImage(this.backgroundImageURL);
  428.                ((Component)this).repaint();
  429.  
  430.                try {
  431.                   this.updateMaxDims(this.getImageDimensions(this.backgroundImage));
  432.                } catch (Exception var11) {
  433.                   this.loadError(this.backgroundImageURL, "background image");
  434.                }
  435.             }
  436.  
  437.             URL badURL = this.fetchImages(this.images);
  438.             if (badURL != null) {
  439.                this.loadError(badURL, "image");
  440.                return;
  441.             }
  442.  
  443.             if (this.soundtrackURL != null && this.soundtrack == null) {
  444.                this.tellLoadingMsg(this.soundtrackURL, "image");
  445.                this.soundtrack = ((Applet)this).getAudioClip(this.soundtrackURL);
  446.                if (this.soundtrack == null) {
  447.                   this.loadError(this.soundtrackURL, "soundtrack");
  448.                   return;
  449.                }
  450.             }
  451.  
  452.             if (this.sounds != null) {
  453.                badURL = this.fetchSounds(this.sounds);
  454.                if (badURL != null) {
  455.                   this.loadError(badURL, "sound");
  456.                   return;
  457.                }
  458.             }
  459.  
  460.             this.clearLoadingMessage();
  461.             this.offScrImage = ((Component)this).createImage(this.maxWidth, this.maxHeight);
  462.             this.offScrGC = this.offScrImage.getGraphics();
  463.             this.offScrGC.setColor(Color.lightGray);
  464.             ((Component)this).resize(this.maxWidth, this.maxHeight);
  465.             this.loaded = true;
  466.             this.error = false;
  467.          } catch (Exception e) {
  468.             this.error = true;
  469.             ((Throwable)e).printStackTrace();
  470.          }
  471.       }
  472.  
  473.       if (!this.userPause) {
  474.          if (this.repeat || this.frameNum < this.images.size()) {
  475.             this.startPlaying();
  476.          }
  477.  
  478.          try {
  479.             if (this.images.size() > 1) {
  480.                for(; this.maxWidth > 0 && this.maxHeight > 0 && this.engine == me; this.setFrameNum(this.frameNum + 1)) {
  481.                   if (this.frameNum >= this.images.size()) {
  482.                      if (!this.repeat) {
  483.                         return;
  484.                      }
  485.  
  486.                      this.setFrameNum(0);
  487.                   }
  488.  
  489.                   ((Component)this).repaint();
  490.                   if (this.sounds != null) {
  491.                      AudioClip clip = (AudioClip)this.sounds.get(this.frameNumKey);
  492.                      if (clip != null) {
  493.                         clip.play();
  494.                      }
  495.                   }
  496.  
  497.                   try {
  498.                      Integer pause = null;
  499.                      if (this.durations != null) {
  500.                         pause = (Integer)this.durations.get(this.frameNumKey);
  501.                      }
  502.  
  503.                      if (pause == null) {
  504.                         Thread.sleep((long)this.globalPause);
  505.                      } else {
  506.                         Thread.sleep((long)pause);
  507.                      }
  508.                   } catch (InterruptedException var10) {
  509.                   }
  510.                }
  511.  
  512.             }
  513.          } finally {
  514.             this.stopPlaying();
  515.          }
  516.       }
  517.    }
  518.  
  519.    public void paint(Graphics g) {
  520.       if (!this.error && this.loaded) {
  521.          if (this.images != null && this.images.size() > 0) {
  522.             if (this.frameNum < this.images.size()) {
  523.                if (this.backgroundImage == null) {
  524.                   this.offScrGC.fillRect(0, 0, this.maxWidth, this.maxHeight);
  525.                } else {
  526.                   this.offScrGC.drawImage(this.backgroundImage, 0, 0, this);
  527.                }
  528.  
  529.                Image image = (Image)this.images.elementAt(this.frameNum);
  530.                Point pos = null;
  531.                if (this.positions != null) {
  532.                   pos = (Point)this.positions.get(this.frameNumKey);
  533.                }
  534.  
  535.                if (pos != null) {
  536.                   this.xPos = pos.x;
  537.                   this.yPos = pos.y;
  538.                }
  539.  
  540.                this.offScrGC.drawImage(image, this.xPos, this.yPos, this);
  541.                g.drawImage(this.offScrImage, 0, 0, this);
  542.                return;
  543.             }
  544.  
  545.             this.dbg("No more animation; drawing last image.");
  546.             g.drawImage((Image)this.images.lastElement(), 0, 0, this);
  547.          }
  548.  
  549.       } else if (this.startUpImage != null) {
  550.          g.drawImage(this.startUpImage, 0, 0, this);
  551.       } else if (this.backgroundImage != null) {
  552.          g.drawImage(this.backgroundImage, 0, 0, this);
  553.       } else {
  554.          g.clearRect(0, 0, this.maxWidth, this.maxHeight);
  555.       }
  556.    }
  557.  
  558.    public void start() {
  559.       if (this.engine == null) {
  560.          this.engine = new Thread(this);
  561.          this.engine.start();
  562.       }
  563.  
  564.    }
  565.  
  566.    public void stop() {
  567.       if (this.engine != null && this.engine.isAlive()) {
  568.          this.engine.stop();
  569.       }
  570.  
  571.       this.engine = null;
  572.    }
  573.  
  574.    public boolean handleEvent(Event evt) {
  575.       if (evt.id != 501) {
  576.          return super.handleEvent(evt);
  577.       } else {
  578.          if (this.loaded) {
  579.             if (this.engine != null && this.engine.isAlive()) {
  580.                if (this.userPause) {
  581.                   this.engine.resume();
  582.                   this.startPlaying();
  583.                } else {
  584.                   this.engine.suspend();
  585.                   this.stopPlaying();
  586.                }
  587.  
  588.                this.userPause = !this.userPause;
  589.             } else {
  590.                this.userPause = false;
  591.                this.setFrameNum(0);
  592.                this.engine = new Thread(this);
  593.                this.engine.start();
  594.             }
  595.          }
  596.  
  597.          return true;
  598.       }
  599.    }
  600. }
  601.